package org.whh.automatic.ui;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.whh.automatic.model.AutoTask;
import org.whh.automatic.model.Step;
import org.whh.automatic.service.AutoTaskService;
import org.whh.automatic.service.TaskExecutorService;
import org.whh.automatic.ui.dialog.DialogManager;

import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.Serial;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 主界面类
 * <p>
 * 该类是应用程序的主窗口，提供以下功能：
 * 1. 显示已保存的自动化任务列表
 * 2. 提供任务的基本操作：
 * - 创建新任务
 * - 编辑现有任务
 * - 运行选中的任务
 * - 删除任务
 * 3. 支持动态值的设置和验证
 * <p>
 * 界面采用现代化的设计风格：
 * - 渐变色标题栏
 * - 圆角按钮
 * - 悬停效果
 * - 合理的间距和布局
 */
@Component
public class MainFrame extends JFrame {
    @Serial
    private static final long serialVersionUID = 1L;

    /**
     * 日志记录器
     */
    private static final Logger logger = LoggerFactory.getLogger(MainFrame.class);

    // 界面颜色常量
    /**
     * 标题栏渐变起始颜色
     */
    private static final Color HEADER_GRADIENT_START = new Color(65, 105, 225);
    /**
     * 标题栏渐变结束颜色
     */
    private static final Color HEADER_GRADIENT_END = new Color(100, 149, 237);
    /**
     * 面板背景色
     */
    private static final Color PANEL_BACKGROUND = new Color(245, 245, 250);
    /**
     * 边框颜色
     */
    private static final Color BORDER_COLOR = new Color(210, 210, 210);
    /**
     * 按钮背景色
     */
    private static final Color BUTTON_BACKGROUND = new Color(70, 130, 180);
    /**
     * 按钮悬停颜色
     */
    private static final Color BUTTON_HOVER = new Color(30, 144, 255);
    /**
     * 按钮文字颜色
     */
    private static final Color BUTTON_TEXT = Color.WHITE;

    /**
     * 任务管理服务
     */
    @Autowired
    private AutoTaskService taskService;

    /**
     * 任务执行服务
     */
    @Autowired
    private TaskExecutorService executorService;

    /**
     * 任务列表控件
     */
    private JList<String> taskList;

    /**
     * 任务列表数据模型
     */
    private DefaultListModel<String> taskListModel;

    /**
     * 构造函数
     * <p>
     * 初始化主窗口，包括：
     * 1. 设置窗口标题和基本属性
     * 2. 应用系统外观
     * 3. 初始化界面组件
     * 4. 设置窗口关闭行为
     */
    public MainFrame() {
        super("自动操作工具");

        try {
            // 设置本地系统外观
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            logger.warn("设置系统外观失败", e);
        }

        // 初始化界面
        initComponents();

        // 设置窗口属性
        setSize(700, 550);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

        // 添加窗口关闭监听器
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                exit();
            }
        });
    }

    /**
     * 初始化界面组件
     * <p>
     * 创建并布局主要的界面组件：
     * 1. 主面板：使用BorderLayout布局
     * 2. 标题面板：包含渐变背景和标题文本
     * 3. 内容面板：包含任务列表
     * 4. 按钮面板：包含各种操作按钮
     */
    private void initComponents() {
        // 创建主面板，带白色背景
        JPanel mainPanel = new JPanel(new BorderLayout(0, 0)) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setColor(Color.WHITE);
                g2d.fillRect(0, 0, getWidth(), getHeight());
                g2d.dispose();
            }
        };
        mainPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));

        // 创建标题面板，带渐变背景
        JPanel titlePanel = new JPanel(new BorderLayout()) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                GradientPaint gp = new GradientPaint(0, 0, HEADER_GRADIENT_START, 0, getHeight(), HEADER_GRADIENT_END);
                g2d.setPaint(gp);
                g2d.fillRect(0, 0, getWidth(), getHeight());
                g2d.dispose();
            }
        };
        titlePanel.setPreferredSize(new Dimension(650, 60));

        // 创建标题标签
        JLabel titleLabel = new JLabel("自动操作工具");
        titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
        titleLabel.setForeground(Color.WHITE);
        titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0));
        titlePanel.add(titleLabel, BorderLayout.WEST);

        // 添加标题面板
        mainPanel.add(titlePanel, BorderLayout.NORTH);

        // 创建内容面板
        JPanel contentPanel = new JPanel();
        contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
        contentPanel.setBackground(PANEL_BACKGROUND);
        contentPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        // 创建任务列表面板
        JPanel listPanel = createListPanel();

        // 创建按钮面板
        JPanel buttonPanel = createButtonPanel();

        // 添加组件到内容面板
        contentPanel.add(listPanel);

        // 添加到主面板，支持滚动
        JScrollPane scrollContent = new JScrollPane(contentPanel);
        scrollContent.setBorder(null);
        scrollContent.getVerticalScrollBar().setUnitIncrement(16);

        mainPanel.add(scrollContent, BorderLayout.CENTER);
        mainPanel.add(buttonPanel, BorderLayout.SOUTH);

        // 设置主面板
        setContentPane(mainPanel);
    }

    /**
     * 创建任务列表面板
     * <p>
     * 创建一个包含JList的面板，用于显示所有已保存的任务。
     * 列表支持单选，具有固定的行高和自定义字体。
     *
     * @return 配置好的任务列表面板
     */
    private JPanel createListPanel() {
        JPanel panel = new JPanel(new BorderLayout(10, 10));
        panel.setBackground(PANEL_BACKGROUND);
        panel.setBorder(createSectionBorder("任务列表"));
        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 400));
        panel.setPreferredSize(new Dimension(600, 350));

        taskListModel = new DefaultListModel<>();
        taskList = new JList<>(taskListModel);
        taskList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        taskList.setFont(new Font("微软雅黑", Font.PLAIN, 14));
        taskList.setFixedCellHeight(30);

        JScrollPane scrollPane = new JScrollPane(taskList);
        scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));

        panel.add(scrollPane, BorderLayout.CENTER);

        return panel;
    }

    /**
     * 创建底部按钮面板
     * <p>
     * 创建包含所有操作按钮的面板：
     * - 新建任务
     * - 编辑任务
     * - 运行任务
     * - 删除任务
     * - 退出
     * <p>
     * 所有按钮都使用统一的样式，包括圆角、渐变色和悬停效果
     *
     * @return 配置好的按钮面板
     */
    private JPanel createButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
        panel.setBackground(Color.WHITE);
        panel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, BORDER_COLOR));

        // 创建各个功能按钮
        JButton newTaskBtn = createStyledButton("新建任务");
        newTaskBtn.setPreferredSize(new Dimension(100, 35));
        newTaskBtn.addActionListener(e -> createTask());

        JButton editTaskBtn = createStyledButton("编辑任务");
        editTaskBtn.setPreferredSize(new Dimension(100, 35));
        editTaskBtn.addActionListener(e -> editTask());

        JButton runTaskBtn = createStyledButton("运行任务");
        runTaskBtn.setPreferredSize(new Dimension(100, 35));
        runTaskBtn.addActionListener(e -> runTask());

        JButton deleteTaskBtn = createStyledButton("删除任务");
        deleteTaskBtn.setPreferredSize(new Dimension(100, 35));
        deleteTaskBtn.setBackground(new Color(198, 40, 40));
        deleteTaskBtn.addActionListener(e -> deleteTask());

        JButton exitBtn = createStyledButton("退出");
        exitBtn.setPreferredSize(new Dimension(100, 35));
        exitBtn.addActionListener(e -> exit());

        // 添加按钮到面板
        panel.add(newTaskBtn);
        panel.add(editTaskBtn);
        panel.add(runTaskBtn);
        panel.add(deleteTaskBtn);
        panel.add(exitBtn);

        return panel;
    }

    /**
     * 创建带样式的按钮
     * <p>
     * 创建一个自定义外观的JButton：
     * - 圆角边框
     * - 渐变背景色
     * - 鼠标悬停效果
     * - 点击效果
     *
     * @param text 按钮文本
     * @return 配置好的按钮
     */
    private JButton createStyledButton(String text) {
        JButton button = new JButton(text) {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                if (getModel().isPressed()) {
                    g2.setColor(BUTTON_BACKGROUND.darker());
                } else if (getModel().isRollover()) {
                    g2.setColor(BUTTON_HOVER);
                } else {
                    g2.setColor(BUTTON_BACKGROUND);
                }

                g2.fillRoundRect(0, 0, getWidth(), getHeight(), 8, 8);
                g2.setColor(BUTTON_TEXT);

                int textWidth = g2.getFontMetrics().stringWidth(getText());
                int textHeight = g2.getFontMetrics().getHeight();
                g2.drawString(getText(), (getWidth() - textWidth) / 2,
                        (getHeight() - textHeight) / 2 + g2.getFontMetrics().getAscent());

                g2.dispose();
            }
        };

        button.setFont(new Font("微软雅黑", Font.BOLD, 14));
        button.setForeground(BUTTON_TEXT);
        button.setBackground(BUTTON_BACKGROUND);
        button.setFocusPainted(false);
        button.setBorderPainted(false);
        button.setContentAreaFilled(false);
        button.setCursor(new Cursor(Cursor.HAND_CURSOR));

        return button;
    }

    /**
     * 创建带样式的分区边框
     * <p>
     * 创建一个带标题的复合边框，包括：
     * - 外层线条边框
     * - 内层空白边距
     * - 自定义字体的标题
     *
     * @param title 边框标题
     * @return 配置好的复合边框
     */
    private CompoundBorder createSectionBorder(String title) {
        TitledBorder titledBorder = BorderFactory.createTitledBorder(
                BorderFactory.createLineBorder(BORDER_COLOR),
                title,
                TitledBorder.LEFT,
                TitledBorder.TOP,
                new Font("微软雅黑", Font.BOLD, 14),
                HEADER_GRADIENT_START);

        return BorderFactory.createCompoundBorder(
                titledBorder,
                BorderFactory.createEmptyBorder(10, 10, 10, 10));
    }

    /**
     * 初始化应用
     * <p>
     * 在Spring容器完成依赖注入后调用，
     * 用于加载和显示任务列表
     */
    public void init() {
        updateTaskList();
    }

    /**
     * 更新任务列表
     * <p>
     * 从服务层获取最新的任务列表并更新界面显示
     */
    private void updateTaskList() {
        taskListModel.clear();

        List<String> taskNames = taskService.getAllTaskNames();
        for (String taskName : taskNames) {
            taskListModel.addElement(taskName);
        }
    }

    /**
     * 创建新任务
     * <p>
     * 打开任务编辑对话框，允许用户创建新的自动化任务。
     * 任务创建成功后，更新任务列表。
     */
    private void createTask() {
        TaskEditDialog dialog = new TaskEditDialog(this, taskService, this::updateTaskList);
        // 使用对话框管理器显示对话框
        DialogManager.getInstance().showDialog(dialog, null);
    }

    /**
     * 编辑选中的任务
     * <p>
     * 打开任务编辑对话框，允许用户编辑选中的任务。
     * 如果没有选中任务，提示用户先选择。
     * 任务编辑成功后，更新任务列表。
     */
    private void editTask() {
        int selectedIndex = taskList.getSelectedIndex();
        if (selectedIndex == -1) {
            JOptionPane.showMessageDialog(
                    this,
                    "请先从列表中选择要编辑的任务。",
                    "请选择任务",
                    JOptionPane.INFORMATION_MESSAGE
            );
            return;
        }

        String taskName = taskList.getModel().getElementAt(selectedIndex);
        AutoTask task = taskService.loadTask(taskName);
        if (task != null) {
            TaskEditDialog dialog = new TaskEditDialog(this, taskService, task, this::updateTaskList);
            // 使用对话框管理器显示对话框
            DialogManager.getInstance().showDialog(dialog, null);
        }
    }

    /**
     * 运行任务
     * <p>
     * 执行选中的自动化任务。执行过程：
     * 1. 验证任务选择和加载
     * 2. 检查并设置动态值
     * 3. 确认执行
     * 4. 最小化窗口
     * 5. 异步执行任务
     * 6. 任务完成后显示结果
     */
    private void runTask() {
        String selectedTask = taskList.getSelectedValue();
        if (selectedTask == null) {
            JOptionPane.showMessageDialog(this, "请先选择要运行的任务", "提示", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        AutoTask task = taskService.loadTask(selectedTask);
        if (task == null) {
            JOptionPane.showMessageDialog(this, "加载任务失败", "错误", JOptionPane.ERROR_MESSAGE);
            return;
        }

        // 检查是否需要设置动态值
        java.util.Set<String> requiredDynamicValues = task.getRequiredDynamicValueNames();
        if (!requiredDynamicValues.isEmpty()) {
            // 添加调试输出
            System.out.println("任务 '" + task.getName() + "' 需要设置 " + requiredDynamicValues.size() + " 个动态值");
            for (String name : requiredDynamicValues) {
                System.out.println("需要设置的动态值: " + name);
            }

            // 收集包含动态值的步骤和对应的动态值名称
            Map<Step, String> stepDynamicValueMap = new HashMap<>();
            for (Step step : task.getSteps()) {
                if (step.needsDynamicValue()) {
                    stepDynamicValueMap.put(step, step.getPasteDynamicName());
                    System.out.println("收集到动态值步骤: " + step.getName() + ", 动态值名称: " + step.getPasteDynamicName());
                }
            }

            System.out.println("收集到 " + stepDynamicValueMap.size() + " 个步骤-动态值映射");

            // 使用新的构造函数创建动态值对话框
            DynamicValueDialog dynamicValueDialog = new DynamicValueDialog(
                    this, "设置动态值", stepDynamicValueMap);

            // 添加调试信息
            System.out.println("准备显示动态值对话框，对话框大小: " + dynamicValueDialog.getSize());

            // 强制对话框置顶
            dynamicValueDialog.setAlwaysOnTop(true);

            // 显示对话框
            dynamicValueDialog.setVisible(true);

            System.out.println("动态值对话框已显示，用户确认: " + dynamicValueDialog.isConfirmed());

            if (!dynamicValueDialog.isConfirmed()) {
                return; // 用户取消了设置动态值
            }

            // 设置动态值
            task.setDynamicValues(dynamicValueDialog.getDynamicValues());

            // 检查是否所有动态值都已设置
            if (!task.areAllDynamicValuesSet()) {
                JOptionPane.showMessageDialog(this,
                        "未设置所有必需的动态值，无法运行任务。",
                        "动态值缺失",
                        JOptionPane.WARNING_MESSAGE);
                return;
            }
        }

        // 确认是否运行
        int option = JOptionPane.showConfirmDialog(this,
                "确认运行任务 '" + task.getName() + "' 吗？\n请确保相关程序已经打开。",
                "确认运行",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE);

        if (option != JOptionPane.YES_OPTION) {
            return;
        }

        // 最小化窗口
        setState(Frame.ICONIFIED);

        // 在新线程中执行任务
        new Thread(() -> {
            try {
                // 执行任务
                executorService.executeTask(task, (status, message) -> {
                    // 显示执行结果
                    SwingUtilities.invokeLater(() -> {
                        // 恢复窗口
                        setState(Frame.NORMAL);

                        if (status) {
                            JOptionPane.showMessageDialog(this,
                                    "任务 '" + task.getName() + "' 执行完成！",
                                    "执行成功",
                                    JOptionPane.INFORMATION_MESSAGE);
                        } else {
                            JOptionPane.showMessageDialog(this,
                                    "任务 '" + task.getName() + "' 执行失败：" + message,
                                    "执行失败",
                                    JOptionPane.ERROR_MESSAGE);
                        }
                    });
                });
            } catch (Exception e) {
                // 处理执行错误
                SwingUtilities.invokeLater(() -> {
                    // 恢复窗口
                    setState(Frame.NORMAL);

                    JOptionPane.showMessageDialog(this,
                            "任务执行出错：" + e.getMessage(),
                            "执行错误",
                            JOptionPane.ERROR_MESSAGE);
                });
            }
        }).start();
    }

    /**
     * 删除任务
     * <p>
     * 删除选中的任务。执行过程：
     * 1. 验证任务选择
     * 2. 确认删除
     * 3. 执行删除操作
     * 4. 显示结果并更新列表
     */
    private void deleteTask() {
        String selectedTask = taskList.getSelectedValue();
        if (selectedTask == null) {
            JOptionPane.showMessageDialog(this, "请先选择要删除的任务", "提示", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        int option = JOptionPane.showConfirmDialog(this,
                "确认删除任务 '" + selectedTask + "' 吗？此操作不可恢复。",
                "确认删除",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.WARNING_MESSAGE);

        if (option != JOptionPane.YES_OPTION) {
            return;
        }

        boolean success = taskService.deleteTask(selectedTask);
        if (success) {
            JOptionPane.showMessageDialog(this,
                    "任务 '" + selectedTask + "' 已删除。",
                    "删除成功",
                    JOptionPane.INFORMATION_MESSAGE);

            // 更新任务列表
            updateTaskList();
        } else {
            JOptionPane.showMessageDialog(this,
                    "删除任务 '" + selectedTask + "' 失败。",
                    "删除失败",
                    JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 退出应用
     * <p>
     * 显示确认对话框，确认后关闭应用程序
     */
    private void exit() {
        int option = JOptionPane.showConfirmDialog(this,
                "确认退出应用吗？",
                "确认退出",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE);

        if (option == JOptionPane.YES_OPTION) {
            dispose();
            System.exit(0);
        }
    }

    /**
     * 显示主界面
     * <p>
     * 设置窗口可见并显示在屏幕中央
     */
    public void showUI() {
        setVisible(true);
    }
}
